/*
**  Copyright (c) 2014 Michael Liu(michael.liu.point@gmail.com).
**
**  Project: Gateway Unified Management Platform
**  File:      wlancliifopt.c
**  Author:  Michael
**  Date:    06/27/2014
**
**  Purpose:
**    wlan cli interface method implement.
*/

/* Include files. */

#include "dpmgr.h"
#include "osdep.h"
#include "pfdep.h"
#include "wlancliifopt.h"
#include <sys/time.h>

/* Macro constant definitions. */

#define INIT_WAIT_TIME	5
#define NANO_PER_MICRO	1000

/* Type definitions. */

typedef struct wlancli_priv {
	volatile int ret;
	volatile int running;
	pthread_t task;
	pthread_attr_t attr;
	pthread_cond_t cond;
	pthread_mutex_t mutex;
	twlan_cli_if_link_status *aps;
} twlancli_priv;

/* Local function declarations. */

static e_ret wlan_cli_if_create(tdp_if * dp_if);
static e_ret wlan_cli_if_destroy(tdp_if * dp_if);
static e_ret wlan_cli_if_enable(tdp_if * dp_if);
static e_ret wlan_cli_if_disable(tdp_if * dp_if);
static e_ret wlan_cli_if_setlinkcfg(tdp_if * dp_if, void *linkcfg, tmask * mask);
static e_ret wlan_cli_if_link(tdp_if * dp_if);
static e_ret wlan_cli_if_unlink(tdp_if * dp_if);
static e_ret wlan_cli_if_collectlinkstat(tdp_if * dp_if);
static e_ret wlan_cli_if_getlinkstat(tdp_if * dp_if, void **linkstat, int *size, tmask * mask);
static e_ret wlan_cli_if_getlinkstatus(tdp_if * dp_if, void **status, int *size, tmask * mask);
static e_ret wlan_cli_if_setnetcfg(tdp_if * dp_if, void *netcfg, tmask * mask);
static e_ret wlan_cli_if_connect(tdp_if * dp_if);
static e_ret wlan_cli_if_disconnect(tdp_if * dp_if);
static e_ret wlan_cli_if_collectnetstat(tdp_if * dp_if);
static e_ret wlan_cli_if_getnetstat(tdp_if * dp_if, void **netstat, int *size, tmask * mask);
static e_ret wlan_cli_if_getnetstatus(tdp_if * dp_if, void **status, int *size, tmask * mask);
static e_ret wlan_cli_if_setledstatus(tdp_if * dp_if, int status);

static void *wlancli_scan_task(void *arg);

static void wlan_cli_if_updateledstatus(tdp_work * me, void *arg);

extern e_ret bridge_remove_member_if(tdata_paths * dp, tdp_if * br_if, tdp_if * member_if);
extern void dp_if_wlan_wps_work(tdp_work * me, void *arg);

/* Macro API definitions. */

/* Global variable declarations. */

e_ret wlan24g_cli_if_prepare(tdp_if * dp_if)
{
	sysmgr_trace_enter();

	dp_if->create = wlan_cli_if_create;
	dp_if->destroy = wlan_cli_if_destroy;
	dp_if->enable = wlan_cli_if_enable;
	dp_if->disable = wlan_cli_if_disable;
	dp_if->setlinkcfg = wlan_cli_if_setlinkcfg;
	dp_if->getlinkcfg = dpif_getlinkcfg_common;
	dp_if->link = wlan_cli_if_link;
	dp_if->unlink = wlan_cli_if_unlink;
	dp_if->collectlinkstat = wlan_cli_if_collectlinkstat;
	dp_if->getlinkstat = wlan_cli_if_getlinkstat;
	dp_if->getlinkstatus = wlan_cli_if_getlinkstatus;
	dp_if->setnetcfg = wlan_cli_if_setnetcfg;
	dp_if->getnetcfg = dpif_getnetcfg_common;
	dp_if->connect = wlan_cli_if_connect;
	dp_if->disconnect = wlan_cli_if_disconnect;
	dp_if->collectnetstat = wlan_cli_if_collectnetstat;
	dp_if->getnetstat = wlan_cli_if_getnetstat;
	dp_if->getnetstatus = wlan_cli_if_getnetstatus;
	dp_if->setledstatus = wlan_cli_if_setledstatus;

	sysmgr_trace_exit();

	return (eRET_SUCCESS);

}

e_ret wlan5g_cli_if_prepare(tdp_if * dp_if)
{
	sysmgr_trace_enter();

	dp_if->create = wlan_cli_if_create;
	dp_if->destroy = wlan_cli_if_destroy;
	dp_if->enable = wlan_cli_if_enable;
	dp_if->disable = wlan_cli_if_disable;
	dp_if->setlinkcfg = wlan_cli_if_setlinkcfg;
	dp_if->getlinkcfg = dpif_getlinkcfg_common;
	dp_if->link = wlan_cli_if_link;
	dp_if->unlink = wlan_cli_if_unlink;
	dp_if->collectlinkstat = wlan_cli_if_collectlinkstat;
	dp_if->getlinkstat = wlan_cli_if_getlinkstat;
	dp_if->getlinkstatus = wlan_cli_if_getlinkstatus;
	dp_if->setnetcfg = wlan_cli_if_setnetcfg;
	dp_if->getnetcfg = dpif_getnetcfg_common;
	dp_if->connect = wlan_cli_if_connect;
	dp_if->disconnect = wlan_cli_if_disconnect;
	dp_if->collectnetstat = wlan_cli_if_collectnetstat;
	dp_if->getnetstat = wlan_cli_if_getnetstat;
	dp_if->getnetstatus = wlan_cli_if_getnetstatus;
	dp_if->setledstatus = wlan_cli_if_setledstatus;

	sysmgr_trace_exit();

	return (eRET_SUCCESS);

}

e_ret wlan_cli_if_create(tdp_if * dp_if)
{
	sysmgr_trace_enter();

	sysmgr_trace_exit();
	return (eRET_SUCCESS);
}

e_ret wlan_cli_if_destroy(tdp_if * dp_if)
{
	sysmgr_trace_enter();

	sysmgr_trace_exit();
	return (eRET_SUCCESS);
}

e_ret wlan_cli_if_enable(tdp_if * dp_if)
{
	e_ret ret;

	sysmgr_trace_enter();
	ret = os_dep_if_up(dp_if->name);
	sysmgr_trace_exit();
	return (ret);
}

e_ret wlan_cli_if_disable(tdp_if * dp_if)
{
	e_ret ret;

	sysmgr_trace_enter();
	ret = os_dep_if_down(dp_if->name);
	sysmgr_trace_exit();
	return (ret);
}

e_ret wlan_cli_if_setlinkcfg(tdp_if * dp_if, void *linkcfg, tmask * mask)
{
	e_ret ret;
	twlan_cli_if_linkcfg *cli_linkcfg;
	twlan_cli_if_linkcfg *new_linkcfg;
	unsigned char auth_mode;
	unsigned char enc_method;
	twlan_sec_key sec_key;

	sysmgr_trace_enter();

	if (!mask_test_bitmask(mask->mask[0], eWLAN_CLI_IF_LINKCFG_MASK0_ALL)) {
		/* No update */
		sysmgr_trace_exit();
		return (eRET_SUCCESS);
	}

	if (dp_if->linkcfg == NULL) {
		cli_linkcfg = malloc(sizeof(*cli_linkcfg));
		if (cli_linkcfg == NULL) {
			sysmgr_err("malloc(%d) failed, err: %d,[%s]\n", sizeof(*cli_linkcfg), errno, strerror(errno));
			memset(mask, 0, sizeof(*mask));
			sysmgr_trace_exit();
			return (eRET_NO_RESOURCE);
		}
		memset(cli_linkcfg, 0, sizeof(*cli_linkcfg));
		dp_if->linkcfg = cli_linkcfg;
		dp_if->linkcfg_size = sizeof(*cli_linkcfg);
	} else {
		cli_linkcfg = (twlan_cli_if_linkcfg *) dp_if->linkcfg;
	}

	new_linkcfg = (twlan_cli_if_linkcfg *) linkcfg;

	if (mask_test_bit(mask->mask[7], eDP_IF_LINKCFG_MASK7_LOAD_CFG)) {
		sysmgr_dbg("dp if[%s], load config.\n", dp_if->name);
		/* Load config. */
		memcpy(cli_linkcfg, new_linkcfg, sizeof(*cli_linkcfg));
	} else {
		/* if NOT call from load config. set enable to true */
		cli_linkcfg->enable = eBOOL_TRUE;
	}

	pf_dep_wlan_set_wsc_conf_mode(dp_if, 0);

	ret = eRET_SUCCESS;
	if (mask_test_bit(mask->mask[0], eWLAN_CLI_IF_LINKCFG_MASK0_SSID)) {
		if (pf_dep_wlancli_set_ssid(dp_if, new_linkcfg->ssid) == eRET_SUCCESS) {
			memcpy(&cli_linkcfg->ssid, &new_linkcfg->ssid, sizeof(new_linkcfg->ssid));
		} else {
			ret = eRET_FAILURE;
			mask_clear_bit(mask->mask[0], eWLAN_CLI_IF_LINKCFG_MASK0_SSID);
		}
	}

	if (mask_test_bit(mask->mask[0], eWLAN_CLI_IF_LINKCFG_MASK0_MAC)) {
		if (pf_dep_wlancli_set_bssid(dp_if, new_linkcfg->mac) == eRET_SUCCESS) {
			memcpy(&cli_linkcfg->mac, &new_linkcfg->mac, sizeof(new_linkcfg->mac));
		} else {
			ret = eRET_FAILURE;
			mask_clear_bit(mask->mask[0], eWLAN_CLI_IF_LINKCFG_MASK0_MAC);
		}
	}

	if (mask_test_bit(mask->mask[0], eWLAN_CLI_IF_LINKCFG_MASK0_CHANNEL)) {
		if (pf_dep_wlancli_set_channel(dp_if, new_linkcfg->channel, new_linkcfg->ext_channel) == eRET_SUCCESS) {
			tdp_if *ap_if;
			struct list_head *each;
			unsigned char ap_if_type;
			tdata_paths *dp = dp_if->data_paths;

			if (dp_if->type == eDP_IF_TYPE_WLAN24G_CLI) {
				ap_if_type = eDP_IF_TYPE_WLAN24G_AP;
			} else {
				ap_if_type = eDP_IF_TYPE_WLAN5G_AP;
			}

			/* Update related AP interface Channel */
			list_for_each(each, &dp->all_ifs) {
				ap_if = list_entry(each, tdp_if, all_list);
				if (ap_if->type == ap_if_type) {
					twlan_ap_if_linkcfg *ap_linkcfg = ap_if->linkcfg;
					if (ap_linkcfg != NULL) {
						ap_linkcfg->channel = new_linkcfg->channel;
						ap_linkcfg->ht_extcha = new_linkcfg->ext_channel;
						break;
					}
				}
			}

			cli_linkcfg->channel = new_linkcfg->channel;
		} else {
			ret = eRET_FAILURE;
			mask_clear_bit(mask->mask[0], eWLAN_CLI_IF_LINKCFG_MASK0_CHANNEL);
		}
	}

	if ((mask_test_bit(mask->mask[0], eWLAN_CLI_IF_LINKCFG_MASK0_AUTH_MODE)) ||
	    (mask_test_bit(mask->mask[0], eWLAN_CLI_IF_LINKCFG_MASK0_ENC_METHOD)) ||
	    (mask_test_bit(mask->mask[0], eWLAN_CLI_IF_LINKCFG_MASK0_SEC_KEY))) {

		if (mask_test_bit(mask->mask[0], eWLAN_CLI_IF_LINKCFG_MASK0_AUTH_MODE)) {
			auth_mode = new_linkcfg->auth_mode;
		} else {
			auth_mode = cli_linkcfg->auth_mode;
		}
		if (mask_test_bit(mask->mask[0], eWLAN_CLI_IF_LINKCFG_MASK0_ENC_METHOD)) {
			enc_method = new_linkcfg->enc_method;
		} else {
			enc_method = cli_linkcfg->enc_method;
		}
		if (mask_test_bit(mask->mask[0], eWLAN_CLI_IF_LINKCFG_MASK0_SEC_KEY)) {
			sec_key = new_linkcfg->sec_key;
		} else {
			sec_key = cli_linkcfg->sec_key;
		}
		if (pf_dep_wlancli_set_sec_stuff(dp_if, auth_mode, enc_method, &sec_key) == eRET_SUCCESS) {
			cli_linkcfg->auth_mode = auth_mode;
			cli_linkcfg->enc_method = enc_method;
			cli_linkcfg->sec_key = sec_key;
		} else {
			ret = eRET_FAILURE;
			mask_clear_bit(mask->mask[0], eWLAN_CLI_IF_LINKCFG_MASK0_AUTH_MODE);
			mask_clear_bit(mask->mask[0], eWLAN_CLI_IF_LINKCFG_MASK0_ENC_METHOD);
			mask_clear_bit(mask->mask[0], eWLAN_CLI_IF_LINKCFG_MASK0_SEC_KEY);
		}
	}

	if ((ret == eRET_SUCCESS) && (cli_linkcfg->enable)) {
		pf_dep_wlancli_set_linkenable(dp_if, eBOOL_TRUE, eBOOL_TRUE);

#ifndef APCLI_BOND_SUPPORT
		{
			tdata_paths *dp;
			tdp_if *other_cli_if;
			unsigned char if_type;
			struct list_head *each;

			/* disable another apcli interface in same bridge. */
			dp = dp_if->data_paths;
			if (dp != NULL) {
				if (dp_if->type == eDP_IF_TYPE_WLAN24G_CLI) {
					if_type = eDP_IF_TYPE_WLAN5G_CLI;
				} else {
					if_type = eDP_IF_TYPE_WLAN24G_CLI;
				}
				list_for_each(each, &dp->all_ifs) {
					other_cli_if = list_entry(each, tdp_if, all_list);
					if ((other_cli_if->dp_idx == dp_if->dp_idx) && (other_cli_if->type == if_type)) {
						pf_dep_wlancli_set_linkenable(other_cli_if, eBOOL_FALSE, eBOOL_TRUE);
						dp_if_do_cmd(other_cli_if, eDP_IF_METHOD_UNLINK, NULL);
						break;
					}
				}
			}
		}
#endif
	}

	sysmgr_trace_exit();
	return (ret);
}

e_ret wlan_cli_if_link(tdp_if * dp_if)
{
	e_ret ret;
	e_bool enable;
	unsigned char old_status;
	twlan_cli_if_linkcfg *cli_linkcfg;
	tdp_work update_led_status;

	sysmgr_trace_enter();

	cli_linkcfg = dp_if->linkcfg;
	if (cli_linkcfg != NULL) {
		enable = cli_linkcfg->enable;
	} else {
		enable = eBOOL_FALSE;
	}
	old_status = dp_if->linkstatus;
	dp_if->linkstatus = eDP_IF_LINK_STATUS_UP;
	ret = pf_dep_wlancli_set_linkenable(dp_if, enable, eBOOL_FALSE);
	if (ret != eRET_SUCCESS) {
		dp_if->linkstatus = old_status;
	}

	/* Set to LED Init Stat. */
	dp_if_set_led_status(dp_if, eLED_STATUS_INIT);

	/* Add to datapath work task for LED update */
	update_led_status.arg = dp_if;
	sprintf(update_led_status.name, "%s" DP_IF_LED_WORK_SUBFIX, dp_if->name);
	update_led_status.work = wlan_cli_if_updateledstatus;

	dp_task_add_work(dp_if->data_paths, &update_led_status);

	sysmgr_trace_exit();
	return (ret);
}

e_ret wlan_cli_if_unlink(tdp_if * dp_if)
{
	e_ret ret;
#ifndef APCLI_BOND_SUPPORT
	tdp_if *br_if;
	tdata_paths *dp;
#endif /* APCLI_BOND_SUPPORT */
	unsigned char old_status;
	tdp_work update_led_status;

	sysmgr_trace_enter();

	old_status = dp_if->linkstatus;
	dp_if->linkstatus = eDP_IF_LINK_STATUS_DOWN;
	ret = pf_dep_wlancli_set_linkenable(dp_if, eBOOL_FALSE, eBOOL_FALSE);
	if (ret != eRET_SUCCESS) {
		dp_if->linkstatus = old_status;
	}

	/* Delete  LED update from datapath work task */
	update_led_status.arg = dp_if;
	sprintf(update_led_status.name, "%s" DP_IF_LED_WORK_SUBFIX, dp_if->name);
	update_led_status.work = wlan_cli_if_updateledstatus;
	dp_task_del_work(dp_if->data_paths, &update_led_status);

	/* Turn off LED. */
	dp_if_set_led_status(dp_if, eLED_STATUS_SIGNAL_NONE);

#ifndef APCLI_BOND_SUPPORT
	if (((dp = dp_if->data_paths) != NULL) && ((br_if = dp_if->data_if) != NULL) &&
	    (br_if->type == eDP_IF_TYPE_BRIDGE)) {
		bridge_remove_member_if(dp, br_if, dp_if);
	}
#endif /* APCLI_BOND_SUPPORT */

	sysmgr_trace_exit();
	return (ret);
}

e_ret wlan_cli_if_collectlinkstat(tdp_if * dp_if)
{
	sysmgr_trace_enter();

	sysmgr_trace_exit();
	return (eRET_SUCCESS);
}

e_ret wlan_cli_if_getlinkstat(tdp_if * dp_if, void **linkstat, int *size, tmask * mask)
{
	sysmgr_trace_enter();

	sysmgr_trace_exit();
	return (eRET_SUCCESS);
}

e_ret wlan_cli_if_getlinkstatus(tdp_if * dp_if, void **status, int *size, tmask * mask)
{

	int rc;
	e_ret ret = eRET_SUCCESS;
	e_ret priv_ret;
	twlancli_priv *priv;
	twlan_cli_if_link_status *hostap;
	struct timespec ts;
	struct timeval tv;

	sysmgr_trace_enter();

	priv = dp_if->priv;
	if (priv == NULL) {
		priv = malloc(sizeof(*priv));
		if (priv == NULL) {
			sysmgr_err("malloc(%d) failed, err: %d,[%s]\n", sizeof(*priv), errno, strerror(errno));
			memset(mask, 0, sizeof(*mask));
			*size = 0;
			*status = NULL;
			sysmgr_trace_exit();
			return (eRET_NO_RESOURCE);
		} else {
			dp_if->priv = priv;
			priv->aps = NULL;
			priv->ret = eRET_NOT_EXIST;
			priv->running = eBOOL_FALSE;
			pthread_mutex_init(&priv->mutex, NULL);
			pthread_attr_init(&priv->attr);
			pthread_cond_init(&priv->cond, NULL);
			pthread_attr_setdetachstate(&priv->attr, PTHREAD_CREATE_DETACHED);
		}
	}

	if (mask_test_bit(mask->mask[0], eWLAN_LINKSTAT_MASK0_CANCEL)) {
		/* Stop Scan process. */
		pthread_mutex_lock(&priv->mutex);
		priv_ret = priv->ret;
		pthread_mutex_unlock(&priv->mutex);
		if (priv_ret != eRET_NOT_EXIST) {
			sysmgr_dbg("\n================ Cancel Scan Thread ================\n");
			rc = pthread_kill(priv->task, SIGTERM);
			sysmgr_dbg("pthread_kill() rc:%d.\n", rc);
			usleep(1000);
			rc = pthread_cancel(priv->task);
			sysmgr_dbg("pthread_cancel() rc:%d.\n", rc);
			usleep(1000);
			rc = pthread_join(priv->task, NULL);
			sysmgr_dbg("pthread_join() rc:%d.\n", rc);
			usleep(1000);
			pthread_mutex_lock(&priv->mutex);
			priv->ret = eRET_NOT_EXIST;
			priv->running = eBOOL_FALSE;
			if (priv->aps != NULL) {
				free(priv->aps);
				priv->aps = NULL;
			}
			pthread_mutex_unlock(&priv->mutex);
		}

		if (mask_test_bit(mask->mask[0], eWLAN_LINKSTAT_MASK0_QUERY)) {
			sysmgr_dbg("\n================ Start Scan Thread ================\n");
			pthread_mutex_lock(&priv->mutex);
			rc = pthread_create(&priv->task, &priv->attr, wlancli_scan_task, (void *)dp_if);
			sysmgr_dbg("pthread_create() rc:%d.\n", rc);
			if (rc != 0) {
				pthread_mutex_unlock(&priv->mutex);
				sysmgr_err("pthread_create() failed, err: %d,[%s]\n", errno, strerror(errno));
				memset(mask, 0, sizeof(*mask));
				*size = 0;
				*status = NULL;
				sysmgr_trace_exit();
				return (eRET_FAILURE);
			}

			gettimeofday(&tv, NULL);
			ts.tv_sec = tv.tv_sec + INIT_WAIT_TIME;
			ts.tv_nsec = tv.tv_usec * NANO_PER_MICRO;

			rc = pthread_cond_timedwait(&priv->cond, &priv->mutex, &ts);
			sysmgr_dbg("pthread_cond_timedwait() rc:%d.\n", rc);
			if (rc != 0) {
				if (rc == ETIMEDOUT) {
					rc = pthread_cancel(priv->task);
					sysmgr_dbg("pthread_cancel() rc:%d.\n", rc);
					rc = pthread_join(priv->task, NULL);
					sysmgr_dbg("pthread_join() rc:%d.\n", rc);
				}
				priv->ret = eRET_NOT_EXIST;
				priv->running = eBOOL_FALSE;
				pthread_mutex_unlock(&priv->mutex);
				memset(mask, 0, sizeof(*mask));
				*size = 0;
				*status = NULL;
				sysmgr_trace_exit();
				return (eRET_FAILURE);
			}
			pthread_mutex_unlock(&priv->mutex);

			*size = 0;
			*status = NULL;
			ret = eRET_SUCCESS;
		}
	} else {
		if (mask_test_bit(mask->mask[0], eWLAN_LINKSTAT_MASK0_QUERY)) {
			/* Query Scan Result. */
			sysmgr_dbg("\n================ Query Scan Result ================\n");
			pthread_mutex_lock(&priv->mutex);
			priv_ret = priv->ret;
			pthread_mutex_unlock(&priv->mutex);
			if (priv_ret == eRET_PENDDING) {
				*size = 0;
				*status = NULL;
				ret = eRET_PENDDING;
			} else {
				rc = pthread_kill(priv->task, SIGTERM);
				sysmgr_dbg("pthread_kill() rc:%d.\n", rc);
				usleep(1000);
				rc = pthread_cancel(priv->task);
				sysmgr_dbg("pthread_cancel() rc:%d.\n", rc);
				rc = pthread_join(priv->task, NULL);
				sysmgr_dbg("pthread_join() rc:%d.\n", rc);

				if (priv_ret == eRET_SUCCESS) {
					pthread_mutex_lock(&priv->mutex);
					if (priv->aps != NULL) {
						*status = priv->aps;
						*size = sizeof(twlan_cli_if_link_status) +
						    priv->aps->counter * sizeof(twlan_cli_if_link_entry);
						priv->aps = NULL;
					} else {
						*size = 0;
						*status = NULL;
					}
					pthread_mutex_unlock(&priv->mutex);

					ret = eRET_SUCCESS;
				} else {
					ret = priv_ret;
				}
			}
		} else {
			/* Get Association information. */
			ret = pf_dep_wlancli_get_linkstatus(dp_if, &hostap);
			if (ret != eRET_SUCCESS) {
				*size = 0;
				*status = NULL;
			} else {
				if (hostap != NULL) {
					*status = hostap;
					*size = sizeof(twlan_cli_if_link_status) + sizeof(twlan_cli_if_link_entry);
				} else {
					*size = 0;
					*status = NULL;
				}
			}
		}
	}

	sysmgr_trace_exit();
	return (ret);
}

e_ret wlan_cli_if_setnetcfg(tdp_if * dp_if, void *netcfg, tmask * mask)
{
	sysmgr_trace_enter();

	sysmgr_trace_exit();
	return (eRET_SUCCESS);
}

e_ret wlan_cli_if_connect(tdp_if * dp_if)
{
	sysmgr_trace_enter();

	sysmgr_trace_exit();
	return (eRET_SUCCESS);
}

e_ret wlan_cli_if_disconnect(tdp_if * dp_if)
{
	sysmgr_trace_enter();

	sysmgr_trace_exit();
	return (eRET_SUCCESS);
}

e_ret wlan_cli_if_collectnetstat(tdp_if * dp_if)
{
	sysmgr_trace_enter();

	sysmgr_trace_exit();
	return (eRET_SUCCESS);
}

e_ret wlan_cli_if_getnetstat(tdp_if * dp_if, void **netstat, int *size, tmask * mask)
{
	sysmgr_trace_enter();

	sysmgr_trace_exit();
	return (eRET_SUCCESS);
}

e_ret wlan_cli_if_getnetstatus(tdp_if * dp_if, void **status, int *size, tmask * mask)
{
	e_ret ret;

	sysmgr_trace_enter();

	ret = dpif_getnetstatus_common(dp_if, (void *)status, size);

	sysmgr_trace_exit();
	return (ret);
}

e_ret wlan_cli_if_setledstatus(tdp_if * dp_if, int status)
{
	int last_status;
	unsigned char led_opt;

	sysmgr_trace_enter();

	last_status = dp_if->led.status;
	switch (status) {
	case eLED_STATUS_SIGNAL_NONE:
	case eLED_STATUS_SIGNAL_LOW:
	case eLED_STATUS_SIGNAL_NORMAL:
	case eLED_STATUS_SIGNAL_HIGH:
		dp_if->led.counter = 2;
		break;
	case eLED_STATUS_SCAN:
		dp_if->led.counter = 30;
		break;

	case eLED_STATUS_WPS_PROCESS:
		dp_if->led.counter = 120;
		break;

	case eLED_STATUS_WPS_SUCCESS:
		dp_if->led.counter = 5;
		break;
	case eLED_STATUS_WPS_FAIL:
		dp_if->led.counter = 5;
		break;

	case eLED_STATUS_WPS_OVERLAP:
		dp_if->led.counter = 5;
		break;

	case eLED_STATUS_INIT:
		if (last_status == eLED_STATUS_SIGNAL_NONE) {
			dp_if->led.counter = 1;
			if (dp_if->type == eDP_IF_TYPE_WLAN24G_CLI) {
				led_opt = eLED_OPT_SET_24G_SIGNAL_NONE;
			} else {
				led_opt = eLED_OPT_SET_5G_SIGNAL_NONE;
			}
			sa_led_opt(dp_if->led.led, led_opt);
		}
		sysmgr_trace_exit();
		return (eRET_SUCCESS);
		break;

	default:
		/* Do Nothing */
		sysmgr_trace_exit();
		return (eRET_INVALID_ARG);
	}
	dp_if->led.status = status;

	if (last_status != status) {
		if (dp_if->type == eDP_IF_TYPE_WLAN24G_CLI) {
			led_opt = eLED_OPT_SET_24G_SIGNAL_NONE + status;
		} else {
			led_opt = eLED_OPT_SET_5G_SIGNAL_NONE + status;
		}
		sa_led_opt(dp_if->led.led, led_opt);
	}

	sysmgr_trace_exit();
	return (eRET_SUCCESS);
}

void wlan_cli_if_updateledstatus(tdp_work * me, void *arg)
{
	e_ret ret;
	unsigned char status;
	tdp_if *dp_if = (tdp_if *) arg;
	twlan_cli_if_link_status *hostap;

	sysmgr_trace_enter();

	sysmgr_dbg("IF[%s], LED Status[%d], Counter: %d\n", dp_if->name, dp_if->led.status, dp_if->led.counter);
	if (dp_if->led.counter-- <= 0) {
		/* Get Link Status, and update LED status. */
		ret = pf_dep_wlancli_get_linkstatus(dp_if, &hostap);
		status = eLED_STATUS_SIGNAL_NONE;
		if ((ret == eRET_SUCCESS) && (hostap != NULL) && (hostap->aps[0].linked == eBOOL_TRUE)) {
			if (hostap->aps[0].signal > 80) {
				status = eLED_STATUS_SIGNAL_HIGH;
			} else if (hostap->aps[0].signal > 50) {
				status = eLED_STATUS_SIGNAL_NORMAL;
			} else if (hostap->aps[0].signal > 20) {
				status = eLED_STATUS_SIGNAL_LOW;
			}
		}
		if (hostap != NULL) {
			free(hostap);
		}
		/* update status */
		if (dp_if->led.status != status) {
			dp_if_set_led_status(dp_if, status);
		}
		dp_if->led.counter = 2;
	}

	sysmgr_trace_exit();

}

void wlancli_scan_task_sig(int sig)
{
	sysmgr_trace_enter();
	sysmgr_err("wlancli_scan_task() Canceled.\n");
	sysmgr_trace_exit();
	pthread_exit(NULL);
}

void *wlancli_scan_task(void *arg)
{

	e_ret ret;
	tdp_if *dp_if = (tdp_if *) arg;
	twlancli_priv *priv;
	twlan_cli_if_link_status *aps;

	sysmgr_trace_enter();

	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);

	if ((dp_if == NULL) || (dp_if->priv == NULL)) {
		sysmgr_trace_exit();
		pthread_exit(NULL);
	}

	priv = (twlancli_priv *) dp_if->priv;

	/* Update LEDs */
	dp_if_set_led_status(dp_if, eLED_STATUS_SCAN);

	signal(SIGTERM, wlancli_scan_task_sig);

	pthread_mutex_lock(&priv->mutex);
	priv->running = eBOOL_TRUE;
	priv->ret = eRET_PENDDING;
	sysmgr_dbg("== wlancli_scan_task() start priv->ret: %d, priv->running[%c] ==\n",
		   priv->ret, priv->running ? 'Y' : 'N');
	pthread_cond_signal(&priv->cond);
	pthread_mutex_unlock(&priv->mutex);

#if 1
	ret = pf_dep_wlancli_scan_aps(dp_if, &aps);
#else
	aps = malloc(sizeof(twlan_cli_if_link_status) + 10 * sizeof(twlan_cli_if_link_entry));
	if (aps != NULL) {
		ret = eRET_SUCCESS;
		memset(aps, 0, (sizeof(twlan_cli_if_link_status) + 10 * sizeof(twlan_cli_if_link_entry)));
		aps->counter = 10;
		strcpy(aps->aps[0].ssid, "test1");
		strcpy(aps->aps[1].ssid, "test2");
		strcpy(aps->aps[2].ssid, "test3");
		strcpy(aps->aps[3].ssid, "test4");
		strcpy(aps->aps[4].ssid, "test5");
		strcpy(aps->aps[5].ssid, "test6");
		strcpy(aps->aps[6].ssid, "test7");
		strcpy(aps->aps[7].ssid, "test8");
		strcpy(aps->aps[8].ssid, "test9");
		strcpy(aps->aps[9].ssid, "test10");
	} else {
		ret = eRET_FAILURE;
	}
	sleep(10);
#endif

	/* Update LEDs */
	dp_if_set_led_status(dp_if, eLED_STATUS_SIGNAL_NONE);
	dp_if_set_led_status(dp_if, eLED_STATUS_INIT);

	pthread_mutex_lock(&priv->mutex);
	priv->ret = ret;
	priv->running = eBOOL_FALSE;
	priv->aps = aps;
	pthread_mutex_unlock(&priv->mutex);
	sysmgr_dbg("== wlancli_scan_task() done! priv->ret: %d, priv->running[%c] aps[%p]==\n",
		   priv->ret, priv->running ? 'Y' : 'N', priv->aps);

	sysmgr_trace_exit();

	pthread_exit(NULL);

}

e_ret dp_wlan_cli_start_wps(tdp_if * dp_if, unsigned char wps_method, unsigned long pin)
{

	tdp_work wlan_wps_work;

	sysmgr_trace_enter();
	if ((wps_method != eWLAN_WPS_DPID_PBC) && (wps_method != eWLAN_WPS_DPID_PIN)) {
		sysmgr_trace_exit();
		return (eRET_INVALID_ARG);
	}

	if ((wps_method == eWLAN_WPS_DPID_PIN) && (pin == 0)) {
		sysmgr_trace_exit();
		return (eRET_INVALID_ARG);
	}

	/* Unlink Interface */
	dp_if_do_cmd(dp_if, eDP_IF_METHOD_UNLINK, NULL);

	/* Set Link Enable to DO WPS */
	pf_dep_wlancli_set_ssid(dp_if, "");
	pf_dep_wlancli_set_bssid(dp_if, "");
	pf_dep_wlancli_set_linkenable(dp_if, eBOOL_TRUE, eBOOL_FALSE);

	pf_dep_wlan_set_wsc_conf_mode(dp_if, 1);
	pf_dep_wlan_set_wsc_conf_status(dp_if, 1, eBOOL_FALSE);
	pf_dep_wlan_set_wsc_mode(dp_if, wps_method);
	if (wps_method == eWLAN_WPS_DPID_PIN) {
		pf_dep_wlan_set_wsc_pin_code(dp_if, pin);
	}
	pf_dep_wlan_set_wsc_get_conf(dp_if, eBOOL_TRUE);

	dp_if->wps.counter = 0;
	dp_if->wps.cfg_method = wps_method;

	dp_if_set_led_status(dp_if, eLED_STATUS_WPS_PROCESS);

	wlan_wps_work.arg = dp_if;
	sprintf(wlan_wps_work.name, "%s" DP_IF_WPS_WORK_SUBFIX, dp_if->name);
	wlan_wps_work.work = dp_if_wlan_wps_work;

	dp_task_add_work(dp_if->data_paths, &wlan_wps_work);
	sysmgr_trace_exit();
	return (eRET_SUCCESS);
}
